#include "musicwindow.h"
#include "ui_musicwindow.h"
#include "common.h"

#include <QDir>
#include <QStringList>
#include <QFileDialog>
#include <QNetworkAccessManager>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonDocument>
#include <QTextCodec>

MusicWindow::MusicWindow(QWidget *parent) : QWidget(parent),
                                            ui(new Ui::MusicWindow)
{
    ui->setupUi(this);

    // 创建对象
    this->player = new QMediaPlayer(this);     // 创建播放器对象
    this->playlist = new QMediaPlaylist(this); // 创建播放列表对象
    this->labelArr = new QVector<QLabel *>();  // 创建歌词标签数组对象
    this->lrcArr = new QVector<LrcFormat>();   // 创建歌词数组对象

    // 设置播放
    playlist->setPlaybackMode(QMediaPlaylist::Loop); // 循环模式
    player->setPlaylist(playlist);

    // 绑定信号槽
    // player发送播放状态信号，onStateChanged接收
    connect(player, SIGNAL(stateChanged(QMediaPlayer::State)), this, SLOT(onStateChanged(QMediaPlayer::State)));
    // playlist发送当前index信号，onPlaylistChanged接收
    connect(playlist, SIGNAL(currentIndexChanged(int)), this, SLOT(onPlaylistChanged(int)));
    // player发送当前文件的总时长信号，onDurationChanged接收
    connect(player, SIGNAL(durationChanged(qint64)), this, SLOT(onDurationChanged(qint64)));
    // player发送当前播放时长信号，onPositionChanged接收
    connect(player, SIGNAL(positionChanged(qint64)), this, SLOT(onPositionChanged(qint64)));

    // 调用函数
    initLrcLabel();

    // 读取数据库中已经记录的音频
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName(QString(DATABASE_PATH) + "music.db");
    db.open();

    QSqlQuery querySearch;
    QString sqlSearch = QString("select * from t_music");
    querySearch.exec(sqlSearch);

    while (querySearch.next())
    {
        QString fileName = querySearch.value(1).toString();
        QString musicPath = querySearch.value(2).toString();
        QString lrcPath = querySearch.value(3).toString();

        qDebug() << "Saved entry: " << fileName << " Path: " << musicPath << " + " << lrcPath;

        Music *mus = new Music();
        mus->pathMusic = musicPath;
        mus->pathLrc = lrcPath;
        playlist->addMedia(QUrl::fromLocalFile(musicPath)); // 添加到播放列表
        mus->name = fileName;
        ui->listWidget->addItem(fileName); // 添加到显示列表
    }

    db.close();
}

MusicWindow::~MusicWindow()
{
    delete ui;
}

// 添加音乐函数
void MusicWindow::addMusic(Music *mus)
{
    // 连接数据库
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName(QString(DATABASE_PATH) + "music.db");
    db.open();

    // 先查找数据库确认没有相同数据再添加
    QSqlQuery querySearch;
    QString sqlSearch = QString("select * from t_music where name='%1'").arg(mus->name);
    querySearch.exec(sqlSearch);

    int count = 0;
    while (querySearch.next())
    {
        count++;
    }

    if (count == 0) // 没有相同数据
    {
        QSqlQuery query;
        QString sql = QString("insert into t_music(name,pathMusic,pathLRC) values('%1','%2','%3');")
                          .arg(mus->name).arg(mus->pathMusic).arg(mus->pathLrc);
        query.exec(sql);

        qDebug() << "添加歌曲：" << mus->name << endl;
    }
    else
        qDebug() << "存在歌曲：" << mus->name << endl;

    // 关闭数据库
    db.close();
}

// 初始化歌词函数
void MusicWindow::initLrcLabel()
{
    QFont font;
    font.setPointSize(14);

    // 初始化歌词标签
    labelArr->clear();
    labelArr->push_back(ui->lyricLine01);
    labelArr->push_back(ui->lyricLine02);
    labelArr->push_back(ui->lyricLine03);
    labelArr->push_back(ui->lyricLine04);
    labelArr->push_back(ui->lyricLine05);
    labelArr->push_back(ui->lyricLine06);
    labelArr->push_back(ui->lyricLine07);

    for (int i = 0; i < 7; i++) // 清理歌词显示label
    {
        labelArr->at(i)->clear();
    }

    lab_timer = new QTimer(this);
    lab_timer->start(200);
    connect(lab_timer, &QTimer::timeout, this, &MusicWindow::lrcArrDisplay);
}

// 初始化歌词数组
void MusicWindow::lrcArr_init()
{
    lrcArr->clear();            // 释放上一首歌曲的歌词所占内存
    for (int i = 0; i < 7; i++) // 清理歌词显示label
    {
        labelArr->at(i)->clear();
    }

    // 连接数据库
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName(QString(DATABASE_PATH) + "music.db");
    db.open();

    QSqlQuery query;
    QString sql = QString("select pathLRC from t_music where name='%1';")
                      .arg(ui->label_musicName->text());
    qDebug() << sql << endl;
    query.exec(sql);

    query.next();
    QString lrcName = query.value(0).toString();
    qDebug() << lrcName << endl;

    // 关闭数据库
    db.close();

    QFile file(lrcName);

    if (!file.exists())
        return; // 文件不存在
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
        return; // 文件打不开

    QTextCodec *code = QTextCodec::codecForName("UTF-8");
    QTextStream in(&file);
    in.setCodec(code);
    in.readLine();
    in.readLine(); // 读取文件，跳过前面两行，所以这里是读取两次
    QString line;
    LrcFormat info;

    while (!in.atEnd())
    {
        line = in.readLine();
        info.time = line.mid(1, 5);
        info.content = line.mid(10);
        lrcArr->append(info);

        qDebug() << info.time << info.content;
    }

    file.close();                // 读取完成之后 关闭文件
    int count = lrcArr->count(); // 显示最前面的几句歌词
    if (count > 0)
        labelArr->at(4)->setText(lrcArr->at(0).content);
    if (count > 1)
        labelArr->at(5)->setText(lrcArr->at(1).content);
    if (count > 2)
        labelArr->at(6)->setText(lrcArr->at(2).content);
}

// 播放状态槽函数
void MusicWindow::onStateChanged(QMediaPlayer::State state)
{
    if (state == QMediaPlayer::PlayingState)
    {
        ui->button_playState->setStyleSheet("border-image: url(:/resources/media/pause.png);");

        emit playStateUpdateSignal(true);
    }
    else
    {
        ui->button_playState->setStyleSheet("border-image: url(:/resources/media/start.png);");

        emit playStateUpdateSignal(false);
    }
}

// 播放列表改变槽函数
void MusicWindow::onPlaylistChanged(int position)
{
    ui->listWidget->setCurrentRow(position);               // 定位当前选中的行
    QListWidgetItem *item = ui->listWidget->currentItem(); // 得到当前行的item

    if (item)
        ui->label_musicName->setText(item->text()); // 显示item的名字
}

// 总时长槽函数
void MusicWindow::onDurationChanged(qint64 duration)
{
    ui->horizontalSlider->setMaximum(duration); // 用当前文件的总时长设置进度条的最大值

    int sec = duration / 1000; // 秒
    int min = sec / 60;        // 分
    sec = sec % 60;            // 余数秒

    durationTime = QString::asprintf("%d:%02d", min, sec);
    ui->label_musicTime->setText(positionTime + "/" + durationTime);

    emit playInfoUpdateSignal(ui->label_musicName->text(), ui->label_musicTime->text(), 0, duration);
}

// 当前时长槽函数
void MusicWindow::onPositionChanged(qint64 position)
{
    if (ui->horizontalSlider->isSliderDown())
    {

        player->setPosition(ui->horizontalSlider->value());
    }

    ui->horizontalSlider->setSliderPosition(position); // 用position设置进度条当前位置

    int sec = position / 1000; // 秒
    int min = sec / 60;        // 分
    sec = sec % 60;            // 余数秒

    positionTime = QString::asprintf("%d:%02d", min, sec);
    ui->label_musicTime->setText(positionTime + "/" + durationTime);
    qDebug() << positionTime << endl;

    emit playInfoUpdateSignal(ui->label_musicName->text(), ui->label_musicTime->text(), position, ui->horizontalSlider->maximum());
}

// 返回主页面按钮槽函数
void MusicWindow::on_button_back_clicked()
{
    emit backSignal();
}

// 添加音乐按钮槽函数
void MusicWindow::on_button_add_clicked()
{
    QString curPath = QDir::homePath(); // 获取用户目录
    QString dlgTitle = "选择音频文件"; // 窗口标题
    QString filter = "音频文件(*.mp3 *.wav *.wma);;mp3文件(*.mp3);;wav文件(*.wav);;wmv文件(*.wmv)"; // 可选择文件
    QStringList fileList = QFileDialog::getOpenFileNames(this, dlgTitle, curPath, filter);

    if (fileList.count() < 1)
        return;
    for (int i = 0; i < fileList.count(); i++)
    {
        Music *mus = new Music();
        mus->pathMusic = fileList[i];

        QString lrcName = fileList[i].split(".mp3")[0] + ".lrc";
        mus->pathLrc = lrcName;

        QString aFile = fileList.at(i);                 // 获取第i个文件名
        playlist->addMedia(QUrl::fromLocalFile(aFile)); // 添加到播放列表

        QFileInfo fileInfo(aFile);
        QString fileName = fileInfo.fileName().split(".")[0]; // 获取不带后缀的文件名
        mus->name = fileName;

        addMusic(mus);
        ui->listWidget->addItem(fileName); // 添加到显示列表
    }

    // 添加完成后默认不播放
}

// 删除音乐按钮槽函数
void MusicWindow::on_button_delete_clicked()
{
    int pos = ui->listWidget->currentRow(); // 获取当前选择的行数

    QListWidgetItem *item = ui->listWidget->takeItem(pos); // 根据行数获取item

    // 连接数据库
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName(QString(DATABASE_PATH) + "music.db");
    db.open();

    QSqlQuery querySearch;
    QString sqlSearch = QString("delete from t_music where name='%1'").arg(item->text());
    //qDebug() << sqlSearch;
    querySearch.exec(sqlSearch);

    delete item;                // 从显示列表删除
    playlist->removeMedia(pos); // 从播放列表删除

    // 关闭数据库
    db.close();
}

// 上一首按钮槽函数
void MusicWindow::on_button_prev_clicked()
{
    int size = ui->listWidget->count();
    int row = ui->listWidget->currentRow();

    if (row == 0) // 第一首的上一首是最后一首
    {
        ui->listWidget->setCurrentRow(size - 1);
        playlist->setCurrentIndex(size - 1);
    }
    else
    {
        row--;
        ui->listWidget->setCurrentRow(row);
        playlist->setCurrentIndex(row);
    }

    lrcArr_init();
}

// 下一首按钮槽函数
void MusicWindow::on_button_next_clicked()
{
    int size = ui->listWidget->count();
    int row = ui->listWidget->currentRow();

    if (row == size - 1) // 最后一首的下一首是第一首
    {
        ui->listWidget->setCurrentRow(0);
        playlist->setCurrentIndex(0);
    }
    else
    {
        row++;
        ui->listWidget->setCurrentRow(row);
        playlist->setCurrentIndex(row);
    }

    lrcArr_init();
}

// 开始/暂停按钮槽函数
void MusicWindow::on_button_playState_clicked()
{
    qDebug() << "Toggle!";

    if (player->state() == QMediaPlayer::PlayingState) // 播放状态点击按钮就暂停
    {
        player->pause();
    }
    else if (player->state() == QMediaPlayer::PausedState) // 暂停状态点击按钮就播发
    {
        if (playlist->currentIndex() < 0)
            playlist->setCurrentIndex(0); // 未选择行默认播放第一首
        player->play();
    }
}

// 双击列表播放槽函数
void MusicWindow::on_listWidget_doubleClicked(const QModelIndex &index)
{
    int rowNo = index.row();
    playlist->setCurrentIndex(rowNo);
    player->play();

    lrcArr_init();
}

// 歌词更新槽函数
void MusicWindow::lrcArrDisplay()
{
    if (this->positionTime == this->durationTime)
    {
        return;
    }

    try
    {
        int sec = positionTime.split(":")[1].toInt();
        int min = positionTime.split(":")[0].toInt();

        QString strLabel;
        strLabel.clear();

        if (min >= 10)
            strLabel = QString::number(min, 10);
        else
            strLabel = "0" + QString::number(min, 10);

        if (sec >= 10)
            strLabel = strLabel + ":" + QString::number(sec, 10);
        else
            strLabel = strLabel + ":0" + QString::number(sec, 10);

        // 歌词显示更新
        int count = lrcArr->count();
        for (int i = 0; i < count; i++)
        {
            if (lrcArr->at(i).time == strLabel)
            {
                labelArr->at(3)->setText(lrcArr->at(i).content);

                if (i - 1 >= 0)
                    labelArr->at(2)->setText(lrcArr->at(i - 1).content);
                else
                    labelArr->at(2)->clear();

                if (i - 2 >= 0)
                    labelArr->at(1)->setText(lrcArr->at(i - 2).content);
                else
                    labelArr->at(1)->clear();

                if (i - 3 >= 0)
                    labelArr->at(0)->setText(lrcArr->at(i - 3).content);
                else
                    labelArr->at(0)->clear();

                if (i + 1 < count)
                    labelArr->at(4)->setText(lrcArr->at(i + 1).content);
                else
                    labelArr->at(4)->clear();

                if (i + 2 < count)
                    labelArr->at(5)->setText(lrcArr->at(i + 2).content);
                else
                    labelArr->at(5)->clear();

                if (i + 3 < count)
                    labelArr->at(6)->setText(lrcArr->at(i + 3).content);
                else
                    labelArr->at(6)->clear();
            }
        }

    } catch (exception) {
        qWarning() << "Error updating lyrics!";
    }
}
